package org.example.Thread01;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;

public class MyTimer {
    private Object locker=new Object();
    private BlockingQueue<MyTask> queue=new PriorityBlockingQueue<>();
    public MyTimer(){
        //创建扫描线程
        Thread thread = new Thread(()->{
            //不断地扫描队列中的任务
            while(true){
                try {
                    //1.从队列中取出任务
                    MyTask task=queue.take();
                    //2.判断到没到执行时间
                    long currentTime=System.currentTimeMillis();
                    if(currentTime>=task.getTime()){
                        //时间到了，执行任务
                        task.getRunnable().run();
                    }else{
                        long waitTime=task.getTime()-currentTime;
                        //没有到时间，重新放回队列
                        queue.put(task);
                        synchronized (locker){
                            //加入等待时间
                            locker.wait(waitTime);
                        }
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        //创建一个后台线程
        Thread daemonThread = new Thread(()->{
            while(true){
                //定时唤醒
                synchronized (locker){
                    locker.notifyAll();
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });
        //设置成后台线程
        daemonThread.setDaemon(true);//不会影响前台进程
        //启动线程
        daemonThread.start();
    }

    /**
     * 添加任务的方法
     * @param runnable 任务
     * @param delay 延时
     * @throws InterruptedException
     */
    public void schedule(Runnable runnable,long delay) throws InterruptedException {
        //根据传出的参数构造一个MyTask
        MyTask task=new MyTask(runnable,delay);
        //把任务放入阻塞队列
        queue.put(task);
        //唤醒等待的线程
        synchronized (locker){
            locker.notifyAll();
        }
    }
}
class MyTask implements Comparable<MyTask>{
    //任务
    private Runnable runnable;
    //任务执行的时间
    private long time;
    //生成构造方法
    public MyTask(Runnable runnable, long delay) {
        //校验任务不能为空
        if(runnable==null){
            throw new IllegalArgumentException("参数不能为空...");
        }
        //时间不能为负数
        if(delay<0){
            throw new IllegalArgumentException("执行时间不能为负数...");
        }
        this.runnable = runnable;
        //计算出任务执行的具体时间
        this.time = delay+System.currentTimeMillis();
    }
    //生成get方法
    public Runnable getRunnable() {
        return runnable;
    }

    public long getTime() {
        return time;
    }

    @Override
    public int compareTo(MyTask o) {
        if(this.time>o.getTime()){
            return 1;
        }else if(this.time<o.getTime()){
            return -1;
        }else{
            return 0;
        }
        //return (int)(this.time-o.getTime());
    }
}
